package com.desire.homework;

import org.apache.commons.codec.digest.DigestUtils;

import javax.imageio.ImageIO;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 文件工具类
 *
 * @author desire
 */
public class _41_FileUtils工具类 {
    public static int num = 0;
    public static long rows = 0;
    public static Map<String, Integer> map = new HashMap<>();
    public static Map<String, Integer> wm = new HashMap<>();

    public _41_FileUtils工具类() {
    }

    public static int count(String dir, String ext) {
        File dirs = new File(dir);
        return count(dirs, ext);
    }

    public static boolean isImage(String img) {
        return isImage(new File(img));
    }

    public static boolean isImage(File img) {
        boolean f = false;
        try {
            var i = ImageIO.read(img);
            int w = i.getWidth();
            int h = i.getHeight();
            int t = i.getType();
            f = true;
        } catch (Exception e) {
            f = false;
        }
        return f;
    }

    public static int count(File dir, String ext) {
        for (File f : Objects.requireNonNull(dir.listFiles())) {
            if (f.isDirectory()) {
                count(f, ext);
            } else if (f.exists() && f.getName().endsWith(ext)) {
                ++num;
            }
        }
        return num;
    }

    public static Map<String, Integer> list(File dir) {
        for (File f : Objects.requireNonNull(dir.listFiles())) {
            if (f.isDirectory()) {
                list(f);
            } else if (f.isFile()) {
                String fn = f.getName();
                int index = fn.lastIndexOf(".");
                String ext = index == -1 ? fn : fn.substring(index);
                if (map.containsKey(ext)) {
                    map.put(ext, map.get(ext) + 1);
                } else {
                    map.put(ext, 1);
                }
            }
        }
        return map;
    }

    public static boolean delFile(String file) {
        return delFile(new File(file));
    }

    public static boolean delFile(File file) {
        boolean f = false;
        if (file.exists()) {
            f = file.delete();
        }
        return f;
    }

    public static void delDir(String dir) {
        delDir(new File(dir));
    }

    public static void delDir(File dir) {
        File[] fs = dir.listFiles();
        if (fs.length == 0) {
            dir.delete();
        } else {
            for (File f : fs) {
                if (f.isDirectory()) {
                    delDir(f);
                } else if (f.isFile()) {
                    f.delete();
                }
            }
        }
        dir.delete();
    }


    public static long countSourceRows(File file) {
        long rows = 0;
        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            rows = br.lines().count();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return rows;
    }

    public static long countDirRows(File dir) {
        for (File f : Objects.requireNonNull(dir.listFiles())) {
            if (f.isDirectory()) {
                countDirRows(f);
            } else if (f.isFile() && f.getName().endsWith(".java")) {
                rows += countSourceRows(f);
            }
        }
        return rows;
    }

    public static boolean isSames(String one, String two) {
        return isSames(new File(one), new File(two));
    }

    public static boolean isSames(File one, File two) {
        boolean f = false;
        if (one.length() == two.length()) {
            File file;
            try (FileInputStream fo = new FileInputStream(one); FileInputStream ft = new FileInputStream(two)) {
                long i = 0;
                while (fo.read() == ft.read()) {
                    ++i;
                    if (i == one.length() * 0.01) {
                        f = true;
                        break;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return f;
    }

    public static boolean isOK(File one, File two) {
        boolean f = false;
        try (var fo = new FileInputStream(one); var ft = new FileInputStream(two)) {
            String f1 = DigestUtils.md5Hex(fo);
            String f2 = DigestUtils.md5Hex(ft);
            if (f1.equalsIgnoreCase(f2)) {
                f = true;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return f;
    }

    public static String getFileType(String file) {
        return getFileType(new File(file));
    }

    public static String getFileType(File file) {
        String e = "unknow";
        var map = new HashMap<String, String>();
        map.put("jpg", "FFD8FF"); // JPEG (jpg）
        map.put("png", "89504E47"); // PNG (png)
        map.put("gif", "47494638"); // GIF (gif)
        map.put("tif", "49492A00"); // TIFF (tif)
        map.put("bmp", "424D"); // windows Bitmap_ ( bmp)
        map.put("dwg", "41433130"); // CAD (dwg)
        map.put("html", "68746D6C3E"); // HTML (html)
        map.put("rtf", "7B5C727466"); // Rich Text Format (rtf)
        map.put("xml", "3C3F786D6C");
        map.put("zip", "504Be304");
        map.put("rar", "52617221");
        map.put("psd", "38425053"); // Photoshop (psd)
        map.put("eml", "44656c69766572792D646174653A"); // Email [thorough only](eml)
        map.put("dbx", "CFAD12FEC5FD746F"); // outlook Express (dbx)
        map.put("pst", "2142444E"); // outiook (pst)
        map.put("xls", "DOCF11Ee"); // MS word
        map.put("doc", "DeCF11Ee"); // MS Excel 注意: word 和 excel的文件头一样
        map.put("mdb", "5374616E64617264204A"); // MS Access (mdb)
        map.put("wpd", "FF575043"); // wordPerfect (wpd)
        map.put("eps", "252150532D41646F6265");
        map.put("ps", "252150532D41646F6265");
        map.put("pdf", "255044462D312E"); // Adobe Acrobat (pdf)
        map.put("qdf", "ACSEBD8F"); // Quicken (qdf)
        map.put("pwl", "E3828596"); // windows Password (pwl)
        map.put("wav", "57415645"); // wave (wav)
        map.put("avi", "41564920");
        map.put("ram", "2E7261FD"); // Real Audio (ram)
        map.put("rm", "2E524D46"); // Real Media (rm)
        map.put("mpg", "eae0e1BA"); //
        map.put("mov", "6D6F6F76"); // Quicktime (mov)
        map.put("asf", "3026B2758E66CF11"); // windows Media (asf)
        map.put("mid", "4D546864"); //MIDI (mid)
        String ext = getFileHeaderInfo(file, 14);
        for (String k : map.keySet()) {
            if (ext.startsWith(map.get(k))) {
                e = k;
                break;
            }
        }
        return e;
    }

    public static String getFileHeaderInfo(File file, int size) {
        StringBuilder sbu = new StringBuilder();
        byte[] buf = new byte[size];
        try (var fis = new FileInputStream(file)) {
            fis.read(buf);
        } catch (IOException e) {
            e.printStackTrace();
        }
        for (byte b : buf) {
            sbu.append(String.format("%02x", b));
        }
        return sbu.toString();
    }

    public static void copyFile(String src, String dst) {
        copyFile(new File(src), new File(dst));
    }

    public static void copyFile(File src, File dst) {
        try (FileInputStream fis = new FileInputStream(src); FileOutputStream fos = new FileOutputStream(dst)) {
            int len;
            byte[] buffer = new byte[4096];
            while ((len = fis.read(buffer)) > 0) {
                fos.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void copyDir(String src, String dst) {
        copyDir(new File(src), new File(dst));
    }

    public static void copyDir(File src, File dst) {
        if (!src.isDirectory()) {
            return;
        }
        if (!dst.exists()) {
            dst.mkdirs();
        }
        for (File f : Objects.requireNonNull(src.listFiles())) {
            if (f.isDirectory()) {
                copyDir(f, new File(dst.getPath(), f.getName()));
            } else if (f.isFile()) {
                copyFile(f, new File(dst.getPath(), f.getName()));
            }
        }
    }

    public static void rename(String file) {
        rename(new File(file));
    }

    public static void rename(File file) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssS");
        Random random = new Random();
        String fn = String.format("%s_%05d", sdf.format(new Date()), random.nextInt(99999)) + getExt(file);
        file.renameTo(new File(file.getPath(), fn));
    }

    public static String getExt(String file) {
        String fn = file.toLowerCase();
        int i = fn.lastIndexOf(".");
        return i == -1 ? fn : fn.substring(i);
    }

    public static String getExt(File file) {
        String fn = file.getName().toLowerCase();
        int i = fn.lastIndexOf(".");
        return i == -1 ? fn : fn.substring(i);
    }

    public static Map<String, Integer> countJdk(String file) {
        return countJdk(new File(file));
    }

    public static Map<String, Integer> countJdk(File file) {
        for (File f : Objects.requireNonNull(file.listFiles())) {
            if (f.isDirectory()) {
                countJdk(f);
            } else if (f.isFile() && f.getName().endsWith(".java")) {
                StringBuilder sbu = new StringBuilder();
                int rows = 0;
                try (var br = new BufferedReader(new FileReader(f))) {
                    while (br.ready()) {
                        sbu.append(br.readLine());
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Pattern pattern = Pattern.compile("[a-zA-Z]{2,}");
                Matcher m = pattern.matcher(sbu.toString());
                while (m.find()) {
                    String w = m.group();
                    if (wm.containsKey(w)) {
                        wm.put(w, wm.get(w) + 1);
                    } else {
                        wm.put(w, 1);
                    }
                }
            }
        }
        return wm;
    }
}
